<?php
namespace proxy;
use yii\base\Object;

class WeixinApiProxy extends Object
{
    public $_host = null;
    public $_url = array();
    public $_cookie = array();
    public $_header = array();
    public $_timeout = null;
    public $header_size = 0;

        //https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
    public function __construct()
    {/*{{{*/
        $this->_host = "api.weixin.qq.com";
        $this->_header = ["Content-Type: application/x-www-form-urlencoded;charset=UTF-8"];
        $this->_timeout = 6;
        parent::__construct();
    }/*}}}*/

    public function handleHeader($ch, $str)
    {/*{{{*/
        $len = strlen($str);
        $this->header_size += $len;
        return $len;
    }/*}}}*/

    public function execute($uri, $params)
    {/*{{{*/
        $this->_url = 'https://'.$this->_host.'/'.$uri.'?'.http_build_query($params);
        
        $this->header_size = 0;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->_url);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/99.99 (compatible; MSIE 99.99; Windows XP 99.99)");
        curl_setopt($ch, CURLOPT_TIMEOUT,$this->_timeout);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'handleHeader'));

        if ($this->_host)
        {
            $this->_header[] = 'Host: ' . $this->_host;
        }

        if ($this->_header)
        {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $this->_header);
        }

        if ($this->_cookie)
        {
            $tmp_cookie = '';
            foreach($this->_cookie as $key => $val)
            {
                $tmp_cookie = $tmp_cookie . $key . '=' . $val . ';'; 
            }
            curl_setopt($ch, CURLOPT_COOKIE,  $tmp_cookie);
        }

        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        $result = curl_exec($ch);
        $curl_info = curl_getinfo($ch);

        curl_close($ch);
        return $this->decodeResponse($result, $curl_info);
    }/*}}}*/

    private function decodeResponse($response, $curl_info)
    {/*{{{*/
        $output = [];
        $output['body'] = substr($response, $this->header_size);
        $header_arr = preg_split('/[\r\n]+/', substr($response, 0, $this->header_size));

        $header = array();
        foreach($header_arr as $one)
        {
            if(empty($one)) continue;
            $pos = strpos($one, ':');
            if($pos) {
                $key = substr($one, 0, $pos);
                $value = substr($one, $pos + 1);
                $header[$key] = trim($value);
            } else {
                $header[$one] = $one;
            }
        }
        $output['headers'] = $header;
        $output['info'] = $curl_info;

        return $this->_handleOutput($output);
    }/*}}}*/
    
    private function _handleOutput($response)
    {/*{{{*/
        if ($response['info']['http_code'] != 200) 
        {
            return false;
        }

        return json_decode($response['body'], true);
    }/*}}}*/

    private function _log($info)
    {/*{{{*/
    }/*}}}*/
    
}
